package vip.wangwenhao.gateway.config;

import com.netflix.hystrix.exception.HystrixRuntimeException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.cloud.gateway.support.TimeoutException;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.server.*;
import vip.wangwenhao.gateway.constants.GatewayConstants;
import vip.wangwenhao.common.enums.ResultCode;
import vip.wangwenhao.common.exception.LimitException;
import vip.wangwenhao.common.result.Result;

import java.util.Map;

/**
 * @author wangwenhao
 */
@Slf4j
public class JsonErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {

    public JsonErrorWebExceptionHandler(ErrorAttributes errorAttributes,
                                        ResourceProperties resourceProperties,
                                        ErrorProperties errorProperties,
                                        ApplicationContext applicationContext) {
        super(errorAttributes, resourceProperties, errorProperties, applicationContext);
    }

    @Override
    protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
        // 这里其实可以根据异常类型进行定制化逻辑
        Throwable error = super.getError(request);
        if (error instanceof HystrixRuntimeException) {
            Throwable cause = error.getCause();
            if (cause instanceof LimitException) {
                return Result.failToMap(ResultCode.TOO_MANY_REQUESTS);
            }
            log.error("", error);
            return Result.failToMap(ResultCode.HYSTRIX_FALLBACK_EXCEPTION, error.getMessage());

        } else if (error instanceof NotFoundException) {
            return Result.failToMap(ResultCode.SERVICE_NOT_FOUND, error.getMessage());
        } else if (error instanceof TimeoutException) {
            return Result.failToMap(ResultCode.TIMEOUT_EXCEPTION);
        } else {
            String path = request.path();
            if (!path.contains(GatewayConstants.FAVICON_ICO)) {
                log.error("{} 请求失败：", path, error);
            }

        }
        return Result.failToMap(ResultCode.ERROR_SERVER_FAILED, error.getMessage());
    }

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }

    @Override
    protected HttpStatus getHttpStatus(Map<String, Object> errorAttributes) {
        // 这里其实可以根据errorAttributes里面的属性定制HTTP响应码
        return HttpStatus.OK;
    }

}